package com.duojuhe.advice;

import com.alipay.api.AlipayApiException;
import com.duojuhe.common.component.dingding.DingDingService;
import com.duojuhe.common.exception.DuoJuHeSystemException;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.ServiceResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;

import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.SQLNonTransientConnectionException;

/**
 * <br>
 * <b>功能：</b>全局异常处理<br>
 *
 * @date 2018/5/25
 */
@Slf4j
@ControllerAdvice
public class ExceptionHandlerAdvice {
    @Resource
    private DingDingService dingDingService;



    @ResponseBody
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ServiceResult methodNotSupportHandle(HttpRequestMethodNotSupportedException e) {
        return ServiceResult.fail("不支持的请求方法!");
    }

    /**
     * 参数验证异常捕捉处理
     */
    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ServiceResult errorHandler(MethodArgumentNotValidException ex) {
        // 参数校验失败信息
        FieldError fieldError = ex.getBindingResult().getFieldError();
        if (fieldError == null) {
            return ServiceResult.fail(ex.getMessage());
        } else {
            return ServiceResult.fail(fieldError.getDefaultMessage());
        }

    }


    @ResponseBody
    @ExceptionHandler(BindException.class)
    public ServiceResult bindExceptionHandle(BindException e) {
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return ServiceResult.fail(message);
    }



    /**
     * 拦截捕捉自定义基础异常
     */
    @ResponseBody
    @ExceptionHandler(value = DuoJuHeException.class)
    public ServiceResult myDuoJuHeExceptionHandler(DuoJuHeException ex) {
        if (ex.getErrorCodes()!=null){
            return ServiceResult.fail(ex.getErrorCodes());
        }else {
            return ServiceResult.fail(ex.getMessage());
        }
    }

    /**
     * 捕捉三方支付异常
     */
    @ResponseBody
    @ExceptionHandler({AlipayApiException.class, WxPayException.class})
    public ServiceResult payApiExceptionHandler(Exception ex) {
        return ServiceResult.fail(ex.getMessage());
    }


    /**
     * 全局异常捕捉处理
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ServiceResult exceptionHandler(Exception ex) {
        log.error("全局异常捕捉处理", ex);
        //发送钉钉通知
        String content = "错误原因：出现异常"+ex;
        dingDingService.dingSendMessage("出现异常",content);
        return ServiceResult.fail("请求出现错误!");
    }


    @ResponseBody
    @ExceptionHandler(NullPointerException.class)
    public ServiceResult dealNullPointerException(NullPointerException ex) {
        log.error("出现空指针", ex);
        //发送钉钉通知
        String content = "错误原因：出现空指针"+ex;
        dingDingService.dingSendMessage("NullPointerException",content);
        return ServiceResult.fail("系统错误!");
    }


    /**
     * 拦截捕捉RuntimeException异常
     */
    @ResponseBody
    @ExceptionHandler(value = RuntimeException.class)
    public ServiceResult runtimeExceptionHandler(RuntimeException ex) {
        log.error("RuntimeException异常", ex);
        //发送钉钉通知
        String content = "错误原因：出现异常"+ex;
        dingDingService.dingSendMessage("RuntimeException",content);
        return ServiceResult.fail(ErrorCodes.FAIL);
    }



    /**
     * 拦截捕捉SQLNonTransientConnectionException异常
     */
    @ResponseBody
    @ExceptionHandler(value = SQLNonTransientConnectionException.class)
    public ServiceResult sqlNonTransientConnectionExceptionHandler(RuntimeException ex) {
        log.error("SQLNonTransientConnectionException异常", ex);
        //发送钉钉通知
        String content = "错误原因：出现异常"+ex;
        dingDingService.dingSendMessage("SQLNonTransientConnectionException",content);
        return ServiceResult.fail(ErrorCodes.FAIL);
    }

    /**
     * 拦截捕捉自定义系统异常
     */
    @ResponseBody
    @ExceptionHandler(value = DuoJuHeSystemException.class)
    public ServiceResult myDuoJuHeSystemExceptionHandler(DuoJuHeSystemException ex) {
        log.error("DuoJuHeSystemException异常", ex);
        //发送钉钉通知
        String content = "错误原因：出现异常"+ex;
        dingDingService.dingSendMessage("DuoJuHeSystemException",content);
        if (ex.getErrorCodes()!=null){
            return ServiceResult.fail(ex.getErrorCodes());
        }else {
            return ServiceResult.fail(ex.getMessage());
        }
    }

}
